Release MCP 0.6.3#32
Merged
Merged
Conversation
ArtyETH06
added a commit
that referenced
this pull request
Jun 19, 2026
Adds workflow #32 (Modify qualification methods) exercising leadbay_set_qualification_methods, and drops the now-stale "read-only" note from #30. Scenario adds a question against an org already at the 5-question cap — exercises the write tool + cap handling while mutating nothing. Live run: 5/5/5/5, invariants 2/2, org questions byte-for-byte unchanged after. Co-Authored-By: Claude <noreply@anthropic.com>
milstan
pushed a commit
that referenced
this pull request
Jun 24, 2026
…ds (#113) * feat(core): retrieve org qualification methods + per-lead custom fields Two new default-surface read composites resolving product#3768: - leadbay_get_qualification_methods — returns the org's AI-agent qualification questions (the "qualification methods") with created_at + lang, plus the caller's is_admin flag and a web-app edit hint. Read-only for everyone; the API exposes no write endpoint for these questions. - leadbay_get_lead_custom_fields — returns the CRM custom-field VALUES on a single lead as {id, name, type, value}. The lead payload embeds each field's definition (verified live), so no /crm/custom_fields join is needed; the catalog is fetched only as a defensive fallback. Fires LEAD_SEEN on read, in parity with the research tools. Both were already partially reachable only via the ADVANCED-gated get_taste_profile / list_mappable_fields (definitions only); the per-lead custom_fields array was silently dropped (untyped on LeadPayload). Adds LeadCustomFieldEntry + LeadPayload.custom_fields, two routing templates, WORKFLOWS.md rows, and registry/audit entries (COMPOSITE_FILE_TOOL_NAMES, TOOLS_WITH_ROUTING, output-schema conformance CASES). Verified live end-to-end on the test org. Co-Authored-By: Claude <noreply@anthropic.com> * test(eval): add eval contracts for qualification-methods + lead-custom-fields Adds the machine-readable yaml expected + yaml scenario blocks for workflows #30 (Org qualification methods) and #31 (Per-lead custom-field values) so /eval can run them. Live run: both 5/5/5/5, invariants green. Co-Authored-By: Claude <noreply@anthropic.com> * feat(core): update + delete CRM custom fields Adds the modify surface for custom fields, completing the read+write set: - leadbay_update_custom_field — rename and/or change type+config in place (POST /crm/custom_fields/{id} → 204, verified live). Partial-merge over the current definition so rename-only keeps the type and retype-only keeps the name. Same EXTERNAL_ID/PRICE config validation as create. - leadbay_delete_custom_field — DELETE /crm/custom_fields/{id} → 204. Destructive (drops the field's values from every lead), so it requires an explicit confirm:true; without it the tool previews the field and does nothing. destructiveHint:true. Both granular-shaped, registered in compositeWriteTools (default surface, write-gated like create_custom_field). Conformance CASES + new unit test files added; live update+delete round-trip verified. Qualification methods intentionally get NO modify tool — the API exposes no write endpoint for ai_agent_questions (every verb 404s); they stay read-only with the web-app edit hint. Co-Authored-By: Claude <noreply@anthropic.com> * feat(core): modify org qualification methods (write) The qualification-questions write endpoint DOES exist — it's the org root POST /organizations/{orgId} with {ai_agent_lead_questions:[string,...]} → 204 (full-replace; confirmed live with the web app's exact payload). My earlier 404 was probing the wrong path (/ai_agent_questions). Adds leadbay_set_qualification_methods: - set / add / remove modes; reads the current list and posts the full resulting array (matches the full-replace endpoint). - shrinking the list requires confirm:true (removing a question changes how every lead is scored); add does not. - enforces the backend cap (max 5 questions) with an actionable hint instead of a raw 400. - invalidates the taste-profile cache after a write. Live-verified: add hits the 5-cap correctly; remove-without-confirm previews; remove+restore round-trips cleanly (account left as found). This supersedes the earlier "no write endpoint" note — qualification methods are now fully modifiable, alongside custom fields. Co-Authored-By: Claude <noreply@anthropic.com> * test(eval): add eval contract for modify-qualification-methods (wf 32) Adds workflow #32 (Modify qualification methods) exercising leadbay_set_qualification_methods, and drops the now-stale "read-only" note from #30. Scenario adds a question against an org already at the 5-question cap — exercises the write tool + cap handling while mutating nothing. Live run: 5/5/5/5, invariants 2/2, org questions byte-for-byte unchanged after. Co-Authored-By: Claude <noreply@anthropic.com> * test(eval): add eval contract for modify-custom-fields (wf 33) Adds workflow #33 (Modify custom fields) exercising the full create → update → delete lifecycle, including the delete confirm-gate. Self-contained: the scenario creates a throwaway field, renames it, and deletes it with confirm, so the run cleans up after itself. Live run: 5/5/5/5, invariants 3/3, catalog byte-for-byte unchanged after (only the pre-existing field remains). Co-Authored-By: Claude <noreply@anthropic.com> * fix(core): point get_qualification_methods at the modify tool The read tool's description + admin hint still said editing happens in the Leadbay web app with "no MCP edit tool yet" — stale since leadbay_set_qualification_methods landed. Repoint the hint, is_admin doc, description, and rendering footnote at leadbay_set_qualification_methods. Confirmed against the backend repo: both modify surfaces (qualification questions + custom fields) are authenticate("admin"), i.e. org-admin only — which every user is for their own org, so the modify tools work for everyone in practice. No per-lead custom-field VALUE write route exists (values flow through the import pipeline only). Co-Authored-By: Claude <noreply@anthropic.com> * test(eval): make wf32 a self-restoring round-trip The previous wf32 scenario ("add a question" against a capped list) let the agent self-confirm a destructive removal to make room, mutating live data. Rewrite it as a remove-then-readd round-trip on a single named question: it nets back to the original set, exercises remove(confirm)+add, and never leaves the org mutated. Live re-run: 5/5/5/5, question set byte-for-byte unchanged. Co-Authored-By: Claude <noreply@anthropic.com> * fix(mcp): reconstruct XDG_RUNTIME_DIR + DBUS for OAuth browser-open on Wayland/Snap OAuth-on-install (.dxt) spawned xdg-open "successfully" but no tab opened on Wayland + Snap-browser setups (the Ubuntu default). Claude Desktop strips XDG_RUNTIME_DIR — which broke the existing WAYLAND_DISPLAY reconstruction (it reads that dir) — and strips DBUS_SESSION_BUS_ADDRESS, so a Snap/Flatpak browser couldn't be reached and the launch silently no-op'd. browserLaunchEnv now rebuilds XDG_RUNTIME_DIR from /run/user/<uid> when stripped, then derives WAYLAND_DISPLAY (wayland-N socket) and DBUS_SESSION_BUS_ADDRESS (<runtimeDir>/bus) from it. Existing values are never overridden. Confirmed live: with the fix a browser tab opens from a fully-stripped env; without it, nothing. New test file oauth-browser-env-wayland.test.ts. Co-Authored-By: Claude <noreply@anthropic.com> * fix(mcp): reconstruct XAUTHORITY for OAuth browser-open on Wayland Follow-up to the XDG_RUNTIME_DIR/WAYLAND/DBUS reconstruction: the browser still failed to open from Claude Desktop's stripped child env because an X11/XWayland browser (Chrome/Brave/Electron) needs the X authority cookie to connect to the display. Without XAUTHORITY the X server rejects the client ("Authorization required... Missing X server") and the browser segfaults — xdg-open returns 0, but no tab opens. browserLaunchEnv now injects XAUTHORITY from the Mutter Xwayland cookie at <runtimeDir>/.mutter-Xwaylandauth.*, falling back to ~/.Xauthority. Existing value never overridden. Confirmed live: with XAUTHORITY the browser launches instead of segfaulting. Test coverage extended. Co-Authored-By: Claude <noreply@anthropic.com> * chore(mcp): bump 0.23.0 -> 0.23.1 so .dxt reinstalls as a real update Claude Desktop won't replace an installed extension with the same version number, so the XAUTHORITY browser-open fix didn't take until the version changed. Bumps package.json + server.json. Co-Authored-By: Claude <noreply@anthropic.com> * fix(core): sanitize custom-field config per type (500 on update/create) leadbay_update_custom_field and leadbay_create_custom_field sent the config object verbatim. The backend's per-type config models are strict (PriceFieldConfig = {currency}, Date/DateTime = {format}, ExternalId = {urlTemplate}, TEXT/NUMBER = none), so any extra key — a stale `format` left from the previous type on a type CHANGE, both url_template + urlTemplate, or a currency on a non-PRICE field — triggers a 500 "JSON deserialization error". Reproduced live on staging: TEXT→PRICE with an over-broad config 500s. Add sanitizeConfigForType (new _custom-field-config.ts) that narrows config to exactly the key(s) the target type accepts, and apply it in both tools before building the request body. Live-verified on staging: TEXT→PRICE/EUR now sends {currency:"EUR"} and succeeds; full create→update→delete lifecycle clean. Co-Authored-By: Claude <noreply@anthropic.com> * fix(core): tolerate stringified custom-field config (PRICE currency dropped) The agent passes config as a JSON STRING (e.g. config:'{"currency":"EUR"}'), not an object. sanitizeConfigForType only read object properties, so a string config yielded no currency → backend 400 "PRICE requires a currency config" on a TEXT→PRICE update even though the rename landed. Observed live on staging. sanitizeConfigForType now JSON-parses a string config before narrowing, and both tools sanitize BEFORE the EXTERNAL_ID url_template check (so that check sees the parsed value too). Live-verified: the exact stringified payload the agent sent now narrows to {currency:"EUR"}. Co-Authored-By: Claude <noreply@anthropic.com> * fix(core): address PR review on qualification + custom-field tools P2 — set_qualification_methods: gate confirm on the ACTUAL removed questions, not on count. A remove+add or `set` that keeps the count the same still drops a scoring question; the old `next.length < previousCount` check let that through without confirm. Now computes the removed set and requires confirm whenever any existing question would be dropped. P2 — get_qualification_methods: fetch ai_agent_questions DIRECTLY instead of via resolveTasteProfile (Promise.allSettled substitutes [] on a rejected fetch). A transient backend/auth failure now surfaces as an error rather than a false "no questions configured" that could lead a caller to overwrite real questions. P3 — create/update_custom_field: the tools parse a stringified config, so the input schema now advertises it (type: ["object","string","null"]) and the param types accept string — making the recovery path valid for schema- validating clients. New tests: same-count swap confirm gate, and fetch-failure-surfaces. Co-Authored-By: Claude <noreply@anthropic.com> * docs(mcp): add 0.23.1 CHANGELOG entry (review P3) The package ships CHANGELOG.md but it started at 0.23.0, so consumers installing 0.23.1 had no release notes for the new qualification-method + custom-field tools. Adds the 0.23.1 entry. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(core): rename qualification_methods → questions + move custom-field tools to composite/ (review) Addresses Milan's PR review: 1. Naming — "qualification methods" introduced a new term for what the UI calls "qualification questions". Renamed both tools + all wording, files, templates, WORKFLOWS rows, tests, CHANGELOG: leadbay_get_qualification_methods → leadbay_get_qualification_questions leadbay_set_qualification_methods → leadbay_set_qualification_questions 2. Classification — "simple getters/setters are considered composites". Moved create/update/delete_custom_field (+ the _custom-field-config helper) from src/tools/ into src/composite/, and added them to COMPOSITE_FILE_TOOL_NAMES (so they carry the _triggered_by provenance mandate like other composites). No behavior change; all gates green (core 463, mcp 466). Co-Authored-By: Claude <noreply@anthropic.com> * docs(core): align confirm schema with same-count swaps (review P3) The set_qualification_questions schema + description said confirm:true was required only when the list gets SHORTER, but the code (correctly) gates on ANY dropped question — so an agent following the contract would make a same-count swap without confirm and get a non-changing preview instead of the edit. Reworded the `confirm` schema description, the tool body, and the rendering note to state that dropping any existing question (incl. a same-count swap or a `questions` replacement omitting a current question) needs confirm; pure additions never do. Behavior unchanged; docs now match it. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Verification